首先來聽首歌吧
這是一個很年輕,我又很喜歡的台灣樂團,希望大家如果喜歡也能一起支持!
今天從到這篇的 2.2.13 繼續看下去,這裡講到 layout 的使用方法
我們先來看看一開始 rails 的 layout 長什麼模樣
<!-- views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
<head>
<title>titile</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
看到這裡,不知道大家有沒有注意到在平常使用 rails view 的時候,怎麼都不用寫上面這些寫 html 的時候一定要寫的東西?就是因為它藏在 layout 裡面,平常他直接會跟著 controller ,基本上在同一個 controller 中的 layout 是一樣的,然後在 body 中才把內容 "讓" 給 view 裡面的內容渲染
那這些 layout 該放在哪裡呢?
如果你的 controller 名字叫做 CandidatesController,那麼他會去找 app/views/layouts/candidates.html.erb 這個檔案當作 layout , 如果沒有這個檔案,他會去找 app/views/layouts/application.html.erb 當作 layout,這些都是 "慣例" ,當然我們也是可以自己設定
class CandidatesController < ApplicationController
layout "qoo"
#...
end
利用 layout 這個方法,我們可以指定 layout 是哪個檔案,上面這個例子中就會去找 app/views/layouts/qoo.html.erb 這檔案
另外,layout 後面也可以接方法,來判斷是要使用哪一份 layout
class CandidatesController < ApplicationController
layout :which_layout
private
def which_layout
@current_user.login? ? "admin" : "visit"
end
end
在上面的例子中,會去判斷 @current_user 是否登入,登入的話會使用 admin layout,否則使用 visit layout
有時候我們會希望使用者回到他在進到這個頁面的前一個來源,這時候可以用 redirect_back
這個方法,在 rails 5 以前是 redirect_to :back
不過要注意的是,使用這個方法的前提是瀏覽器會回報 HTTP_REFERER
這個 error ,但有時候瀏覽器並不是丟這個 error 而是丟一個例外,這時候畫面就會爆掉,接下來說明解決方法
在 rails 5 以前解決這個問題有點麻煩,必須去抓這個例外錯誤
class CandidatesController < ApplicationController
rescue_from ActionController::RedirectBackError, with: :redirect_to_default
def vote
@candidate = Candidate.find params[:id]
@candidate.vote
redirect_to :back
end
private
def redirect_to_default
redirect_to root_path
end
end
上面這個例子是說,當例外發生的時候,我就把瀏覽器導至首頁
現在變得比較簡單了,可以用 fallback_location
這個方法
class CandidatesController < ApplicationController
def vote
@candidate = Candidate.find params[:id]
@candidate.vote
redirect_back(fallback_location: root_path)
end
end
2.3 中提到,我們會在某個條件成功或失敗的情況下,使用 render
或者 redirect_to
讓使用者看到跳轉的畫面,那redirect_to
跟 render
有什麼不同?
redirect_to 是叫瀏覽器送出新的 request 給這個目的地的 url
render 則是請瀏覽器借用哪個畫面做為回應
在 2.3.2 中, Rails guide 給了一個講解的很清楚的例子,我們這裡直接借用
# redirect_to 版本
def index
@books = Book.all
end
def show
@book = Book.find_by(id: params[:id])
if @book.nil?
redirect_to action: :index
end
end
# render 版本
def index
@books = Book.all
end
def show
@book = Book.find_by(id: params[:id])
if @book.nil?
@books = Book.all
flash.now[:alert] = "Your book was not found"
render "index"
end
end
乍看之下 redirect_to
的程式碼比較簡短,但我們透過瀏覽器的角度來看看這件事情
在 redirect_to
版本中,我們嘗試去找這本 @book ,但發現並沒有這本書,這時候 controller 要求瀏覽器去 index 的頁面,我們轉到這個網址來,發現需要 index 的 view 跟 資料庫中的 @books 資訊,因此再去抓這些東西回來到瀏覽器上
在 render
版本中,我們同樣沒找到這本書,這時候 controller 請我們先抓資料庫中的 @bookd 資料,並請瀏覽器渲染出 index 的畫面,需要 @books 的地方就把資料套上去
從上面兩個說明中,應該可以知道在這個例子中 redirect_to
多繞了一圈,因此效能較差,這種情況下建議使用 render
參考資料
rails guide
Rails 5 improves redirect_to :back with new redirect_back method
本文章同步分享於 http://anthonychao.site/